var RIP = function () {

    var Rip = function (graph) {
        this.workers = {};
        this.graph = graph;
		this.onFinish = null;
		this.paths = {};
		for (var v in this.graph){
			this.paths[v] = null;
		}
        if(typeof graph != 'undefined'){
            this.v_num = _.keys(graph).length;
        }else{
            this.v_num = 0;
        }
        this.workers_finnished_no = 0;
        this._start_workers(graph);
        this.computations_counter = 0;
        this.final_paths = {};
    };

    Rip.constructor = Rip;

    Rip.prototype.compute = function (pOnFinish) {
		this.onFinish = pOnFinish;
        _.each(this.workers, function (w) {
            w.postMessage({
                'msg': 'start'
            });
        })
    };

    Rip.prototype._start_workers = function (graph) {
        var _this = this;
        _.each(graph, function (node, key) {
            _this._start_worker(key, node);
        });
    };

    Rip.prototype._start_worker = function (key, node) {
        var w = new Worker('worker.js');
        var _this = this;
        w.onmessage = function (msg) {
            _this._worker_handler(key, msg);
        };
        this.workers[key] = w;
        w.postMessage({'msg': 'init', 'name': key, 'node': node});
    };

    Rip.prototype._worker_handler = function (key, msg) {

        if (msg.data.msg == 'consoleNO') {
            var args = [];
            _.each(msg.data.args, function (arg) {
                args.push(JSON.parse(arg));
            });
            console.log.apply(console, args);
            this.last_console = args;

        } else if (msg.data.msg == 'update') {
            var _this = this;
            //console.log('UPDATE received', msg.data);
            _.each(msg.data.neighbors, function (neighbor_name) {
                _this.workers[neighbor_name].postMessage(
                    {
                        'msg': 'update',
                        'nexthop': msg.data.nexthop,
                        'neighbor_D': msg.data.neighbor_D
                    }
                );
                _this.computations_counter++;
            });
        } else if (msg.data.msg == 'computation_finished') {
            this.computations_counter--;
            if (this.computations_counter == 0) {
                console.log("STOP");
                this.do_finish();
            }
        } else if (msg.data.msg == 'finished') {
            this.workers_finnished_no++;
            this.paths[msg.data.name] = msg.data.paths;
            _.extend(this.final_paths, this.paths);
			this.workers[key].terminate();

            if( this.workers_finnished_no == this.v_num){
                console.log('RESULTS', this.final_paths)
				if (typeof(this.onFinish) == "function") {
					this.onFinish(this.final_paths);
				}
            }
        }
    };

    Rip.prototype.do_finish = function () {
        _.each(this.workers, function (w) {
            w.postMessage({
                'msg': 'get_final_state'
            });
        });
    };

    return {'Rip': Rip};

}();
